package org.semanticflash.rdf.graph.redirection
{

	
	import com.bigflexlib.etc.alias.AliasContext;
	
	import flash.utils.Dictionary;
	
	import org.semanticflash.rdf.triple.RDFTriple;
	import org.semanticflash.rdf.values.IRI;
	import org.semanticflash.rdf.values.RDFValue;

	
	
	
	/**
	 * 
	 * @author aldo.bucchi@gmail.com
	 * 
	 */	
	public class RDFRedirectionContext
	{
	
	
		
		internal var aliasContext:AliasContext;
		
	
	
	
		////////////////////////////////////////////////////
		// constructor
		////////////////////////////////////////////////////
	
	
	
		/**
		 * 
		 * @param iriCompareFunction
		 * 		Defaults to an internal function that compares iris using natural comparison
		 * 		over their IRI.uid property
		 * 
		 * 
		 */		
		public function RDFRedirectionContext( iriCompareFunction:Function = null  )
		{

			
			if ( iriCompareFunction == null )
			{
				iriCompareFunction = compareIRIsBasedOnID;
			}
			
			aliasContext = new AliasContext( iriCompareFunction );
		}
		

		
		private function compareIRIsBasedOnID( iri1:IRI, iri2:IRI ):int
		{
			if ( iri1 === iri2 )
				return 0;
			
			if ( iri1.uid > iri2.uid )
				return 1;
			
			return -1;
			
		}
		
		
		
		
		
		public function eq( iri1:IRI, iri2:IRI ):Boolean
		{
			return aliasContext.eq( iri1, iri2 );		
		}
	
		
		public function neq( iri1:IRI, iri2:IRI ):Boolean
		{
			return aliasContext.neq( iri1, iri2 );
		}
		
		
		public function neqMany( pairs:Array ):Boolean
		{
			return aliasContext.neqMany( pairs );
		}
		
		
		
		

		/////////////////////////////////////////////////////////////////
		//////////////////// IRI Redirections ///////////////////////////
		/////////////////////////////////////////////////////////////////
		

		private var iriRedirections:Dictionary = new Dictionary(  );




		public function getIRIRedirection( iri:IRI ):IRIRedirection
		{
			if ( ! iriRedirections[ iri ] )
			{
				iriRedirections[ iri ] = new IRIRedirection( iri, this );
			}
			
			return iriRedirections[ iri ] as IRIRedirection;
		}
		



		/**
		 * 
		 * Returns the redirected term.
		 * This is a convenience method that allows you to pass an RDFValue, IRI or NULL
		 * and will only cannonicalize relevant IRIs.
		 * The rest of the values simply pass thru
		 * 
		 * @param term
		 * @return 
		 * 
		 */
 		public function cannonicalize( term:RDFValue ):RDFValue
		{
			
			if ( term == null )
				return null;
				
			if ( ! term is IRI )
				return term;
				
				
			return getIRIRedirection( term as IRI ).cannonical;
			
		}






		/////////////////////////////////////////////////////////////////
		//////////////////// Triple Redirections ////////////////////////
		/////////////////////////////////////////////////////////////////

		private var tripleRedirections:Dictionary = new Dictionary( true );


		/**
		 * 
		 * Smushing is implemented at the graph level. That means that the graph
		 * is responsible for replacing statements containing non-cannonical terms by their
		 * cannonical counterparts.
		 * 
		 * 
		 * 
		 * @param iri
		 * @return 
		 * 
		 */
		public function getTripleRedirection( triple:RDFTriple ):RDFTripleRedirection
		{
			if ( ! tripleRedirections[ triple ] )
			{
				tripleRedirections[ triple ] = new RDFTripleRedirection( triple, this );
			}
			
			return tripleRedirections[ triple ] as RDFTripleRedirection;
		}		
		
		
		
		
		
		
		
		
	}
}